package org.example.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/4/20
 * Email haijunzhou@hnit.edu.cn
 */
//@Component
@Aspect
public class MyAspect {

//    long beginTime;


    // 前置增强
    @Before("execution(* org.example..StoreDao.*(..))")
    public void selectBefore(JoinPoint jp){
//        beginTime = System.currentTimeMillis();
        // JoinPoint 封装了方法信息
        System.out.println("jp.getSignature() = " + jp.getSignature());
        System.out.println("jp.getArgs() = " + Arrays.toString(jp.getArgs()));
        System.out.println("jp.getTarget() = " + jp.getTarget());
    }

    @Pointcut("execution(* org.example..select*(..))")
    public void myPointcut(){

    }

    @After("myPointcut()")
    public void selectAfter(JoinPoint jp){
//        long endTime = System.currentTimeMillis();
        System.out.println("=========== 后置增强 ===========" + jp.getSignature());
    }

    @Before("myPointcut()")
    public void selectAfter1(JoinPoint jp){
//        long endTime = System.currentTimeMillis();
        System.out.println("=========== 前置增强 ===========" + jp.getSignature());
    }

    @After("execution(* org.example..select*(..))")
    public void selectAfter2(JoinPoint jp){
//        long endTime = System.currentTimeMillis();
        System.out.println("=========== 后置增强 ===========" + jp.getSignature());
    }

    // res 标识业务方法的返回结果
    @AfterReturning(value = "myPointcut()", returning = "res")
    public void afterReturning(JoinPoint jp, Object res){
        System.out.println("=========== 返回增强 ===========" + jp.getSignature());
        System.out.println("=========== 返回增强 ===========" + res);
    }

    // 异常增强, e 标识业务方法的异常
    @AfterThrowing(value = "myPointcut()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Throwable e){
        System.out.println("=========== 异常增强 ===========" + jp.getSignature());
        System.out.println("=========== 异常增强 ===========" + e);
    }

    /**
     * 环绕增强的连接点  ProceedingJoinPoint 是 JoinPoint 的子类
     * ProceedingJoinPoint 提供执行业务方法的方法
     * 环绕增强的放回值, 就是业务方法的返回值
     * @param pjp
     */
    @Around(value = "myPointcut()")
    public Object around(ProceedingJoinPoint pjp){
        try {
            // 前置拦截
            long beginTime = System.currentTimeMillis();
            System.out.println("############ 环绕 前 ##############");
            // 执行业务方法
            Object proceed = pjp.proceed();
            long endTime = System.currentTimeMillis();
            long times = endTime - beginTime;
            System.out.println(pjp.getSignature()+ " 共耗时: " + times);
            System.out.println("############ 环绕 后 ##############");
            // 返回业务方法的结果
            return proceed;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

}
